package studio.raptor.databus.graph.rule.original;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.assertj.core.util.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author jack
 * @since 1.0
 */
public class OriginalSort {

  private static final Logger logger = LoggerFactory.getLogger(OriginalSort.class);

  public static Set<String> dependSet = new HashSet<String>();//记录一个事件要依赖多少个eventId，利用set存放的目的是为了去除重复


  //初始化6个map,这些map存放所有事件的被依赖关系
  public  Map<Long, String> map1 = new HashMap<Long, String>();
  public  Map<Long, String> map2 = new HashMap<Long, String>();
  public  Map<Long, String> map3 = new HashMap<Long, String>();
  public  Map<Long, String> map4 = new HashMap<Long, String>();
  public  Map<Long, String> map5 = new HashMap<Long, String>();
  public  Map<Long, String> map6 = new HashMap<Long, String>();

  //6个反向map
  public  Map<String, Object> reverseMap1 = new HashMap<String, Object>();
  public  Map<String, Object> reverseMap2 = new HashMap<String, Object>();
  public  Map<String, Object> reverseMap3 = new HashMap<String, Object>();
  public  Map<String, Object> reverseMap4 = new HashMap<String, Object>();
  public  Map<String, Object> reverseMap5 = new HashMap<String, Object>();
  public  Map<String, Object> reverseMap6 = new HashMap<String, Object>();

  public OriginalSort() {

  }


  public Set<String> sort(CsipC2uEvents c2uEvents, Map<String, List<Long>> csipC2uParam) {

    dependSet = Sets.newHashSet();

    String boActionType = c2uEvents.getOrderTypeId();
    boActionType = "," + boActionType + ",";


    doRule1(c2uEvents, boActionType, csipC2uParam);
    doRule2(c2uEvents, boActionType, csipC2uParam);
    doRule3(c2uEvents, boActionType, csipC2uParam);
    doRule4(c2uEvents, boActionType, csipC2uParam);
    doRule5(c2uEvents, boActionType, csipC2uParam);
    doRule6(c2uEvents, boActionType, csipC2uParam);

    if (dependSet.contains(c2uEvents.getEventId())) {
      logger.debug("remove myself：" + c2uEvents.getEventId());
      dependSet.remove(c2uEvents.getEventId());
    }

    return dependSet;
  }

  /**
   * 规则一：
   * 依赖条件： 如果当前任务的客户ID在本规则的map中存在，则构成依赖，被依赖任务ID从map对应位置取得；
   * 被依赖条件： 如果当前任务的动作=新增客户，则产生一条被依赖条件，依赖判断标识=当前任务的客户ID，依赖判断任务ID=当前任务ID； 1 & 4
   */
  private  void doRule1(CsipC2uEvents c, String boActionType, Map<String, List<Long>> map) {
    Long partyId = c.getPartyId();
    boolean isPartyIdExists = false;
    if (partyId != null && partyId > 0) {
      isPartyIdExists = (map1.get(partyId) == null) ? false : true;
      //依赖关系
      if (isPartyIdExists) {//如果存在，产生一条依赖关系，放入set
        logger.debug("-----put in set " + c.getEventId());
        dependSet.add(map1.get(c.getPartyId()));
      }
      //被依赖关系
      //如果当前任务的动作=新增客户，则产生一条被依赖条件，依赖判断标识=当前任务的客户ID，依赖判断任务ID=当前任务ID
      if (boActionType.indexOf("C1") >= 0) {//新增客户
        //插入反向map
        String oldEventId = map1.get(partyId);//找到反相对应关系
        reverseMap1.remove(oldEventId);
        reverseMap1.put(c.getEventId(), partyId);
        map1.put(partyId, c.getEventId());
        logger.debug("map1.put:" + partyId + " value:" + c.getEventId());
      }
    }
  }

  /**
   * 规则二：
   * 依赖条件： 如果当前任务的账户ID在本规则的map中存在，则构成依赖，被依赖任务ID从map对应位置取得；
   * 被依赖条件： 如果当前任务的动作=新增账户，则产生一条被依赖条件，依赖判断标识=当前任务的账户ID，依赖判断任务ID=当前任务ID
   * 说明:正向map是一对多的关系，比如一个eventId对应多个acctId
   * 反向map是多对一的关系,比如一个acctId对应多个eventId
   * 要建立正向map与反向map一一对应的关系，在map值替换的时候，需要先把老值删除，还要判断老map中的值是否都清空了才能删除
   */
  private  void doRule2(CsipC2uEvents c, String boActionType, Map<String, List<Long>> map) {
    List<Long> acctList = null;
    acctList = map.get("ACCOUNTS");
    Map<Long, String> innerAcctMap = new HashMap<Long, String>();
    Map<Long, String> oldInnerAcctMap = new HashMap<Long, String>();
    boolean isAcctIdExists = false;
    if (acctList != null && acctList.size() > 0) {
      for (Long acctId : acctList) {
        isAcctIdExists = (map2.get(acctId) == null) ? false : true;
        //依赖关系
        if (isAcctIdExists) {//如果存在，产生一条依赖关系，放入set
          logger.debug("-----do dependSet acctId:" + acctId);
          dependSet.add(map2.get(acctId));
        }
        //被依赖关系
        //如果当前任务的动作=新增账户，则产生一条被依赖条件，依赖判断标识=当前任务的账户ID，依赖判断任务ID=当前任务ID
        if ((boActionType.indexOf("A1") >= 0)) {//新增账户
          String oldEventId = map2.get(acctId);//找到反相对应关系
          logger.debug("oldEventId:" + oldEventId);
          if (oldEventId != null) {
            oldInnerAcctMap = (Map<Long, String>) reverseMap2
                .get(oldEventId);// 找到反向map
            if (oldInnerAcctMap != null && oldInnerAcctMap.size() > 0) {
              oldInnerAcctMap.remove(acctId);
            }
            if (oldInnerAcctMap != null && oldInnerAcctMap.size() == 0) {
              reverseMap2.remove(oldEventId);
            }
          }
          map2.put(acctId, c.getEventId());
          innerAcctMap.put(acctId, c.getEventId());
        }
      }
      reverseMap2.put(c.getEventId(), innerAcctMap);
    }
  }

  /**
   * 规则三： 依赖条件：如果当前任务的产品ID在本规则的map中存在，则构成依赖，被依赖任务ID从map对应位置取得； 被依赖条件：
   * 如果当前任务的动作=产品动作，如果存在依赖，则更新依赖判断任务ID=当前任务ID，否则则产生一条被依赖条件，依赖判断标识=当前任务的产品ID，依赖判断任务ID=当前任务ID	 *
   */
  private  void doRule3(CsipC2uEvents c, String boActionType, Map<String, List<Long>> map) {
    Long prodId = c.getProdId();
    boolean isProdIdExists = false;
    List<Long> offerProdList = map.get("OFFERS2PRODID");

    //销售品变更的时候，有依赖产品的，需要插入到依赖关系
    if (offerProdList != null) {
      for (Long offerProdId : offerProdList) {
        isProdIdExists = (map3.get(offerProdId) == null) ? false : true;
        if (isProdIdExists) {//如果存在，产生一条依赖关系，放入set
          logger.debug("-----do offerprod dependSet:" + c.getEventId());
          dependSet.add(map3.get(offerProdId));
        }
      }
    }

    if (prodId != null && prodId > 0) {
      isProdIdExists = (map3.get(prodId) == null) ? false : true;
      //依赖关系
      if (isProdIdExists) {//如果存在，产生一条依赖关系，放入set
        logger.debug("-----do rule3 dependSet:" + c.getEventId());
        dependSet.add(map3.get(c.getProdId()));
      }
      //被依赖关系
      //产品ID<>null或者<>0 则表示是产品动作
      //如果当前任务的动作=产品动作，如果存在依赖，则更新依赖判断任务ID=当前任务ID，否则则产生一条被依赖条件，依赖判断标识=当前任务的产品ID，依赖判断任务ID=当前任务ID
      String oldEventId = map3.get(prodId);
      reverseMap3.remove(oldEventId);
      reverseMap3.put(c.getEventId(), prodId);
      map3.put(prodId, c.getEventId());
    }
  }

  /**
   * 规则四：
   * 依赖条件：如果当前任务的动作=客户变更，如果当前任务的客户ID在本规则的map中存在，则构成依赖，被依赖任务ID从map对应位置取得；1&6
   * 被依赖条件：如果当前任务的动作=客户变更，如果存在依赖，则更新依赖判断任务ID=当前任务ID，否则则产生一条被依赖条件，依赖判断标识=当前任务的客户ID，依赖判断任务ID=当前任务ID
   */
  private  void doRule4(CsipC2uEvents c, String boActionType, Map<String, List<Long>> map) {
    boolean isPartyIdExists = false;
    Long partyId = c.getPartyId();
    if (partyId != null && boActionType.indexOf("C2") >= 0) {//客户变更
      isPartyIdExists = (map4.get(partyId) == null) ? false : true;
      //依赖关系
      if (isPartyIdExists) {//如果存在，产生一条依赖关系，放入set
        logger.debug("-----do rule4 isPartyIdExists:" + isPartyIdExists);
        dependSet.add(map4.get(c.getPartyId()));
      }
      //被依赖关系
      //如果当前任务的动作=客户变更，如果存在依赖，则更新依赖判断任务ID=当前任务ID，否则则产生一条被依赖条件，依赖判断标识=当前任务的客户ID，依赖判断任务ID=当前任务ID
      String oldEventId = map4.get(partyId);
      reverseMap4.remove(oldEventId);
      reverseMap4.put(c.getEventId(), partyId);
      map4.put(partyId, c.getEventId());
    }
  }

  /**
   * 规则五：
   * 依赖条件：如果当前任务的动作=账户变更，如果当前任务的账户ID在本规则的map中存在，则构成依赖，被依赖任务ID从map对应位置取得； 2 &7
   * 被依赖条件： 如果当前任务的动作=账户变更，如果存在依赖，则更新依赖判断任务ID=当前账户ID，否则则产生一条被依赖条件，依赖判断标识=当前任务的客户ID，依赖判断任务ID=当前任务ID
   */
  private  void doRule5(CsipC2uEvents c, String boActionType, Map<String, List<Long>> map) {
    boolean isAcctIdExists = false;
    Map<Long, String> innerAcctMap = new HashMap<Long, String>();
    Map<Long, String> oldInnerAcctMap = new HashMap<Long, String>();//老反向
    List<Long> acctList = null;
    acctList = map.get("ACCOUNTS");
    if (boActionType.indexOf("A2") >= 0) {//账户变更
      for (Long acctId : acctList) {
        isAcctIdExists = (map5.get(acctId) == null) ? false : true;
        //依赖关系
        if (isAcctIdExists) {//如果存在，产生一条依赖关系，放入set
          logger.debug("-----do rule5 isAcctIdExists:" + isAcctIdExists);
          dependSet.add(map5.get(acctId));
        }
        //被依赖关系

        String oldEventId = map5.get(acctId);
        logger.debug("oldEventId:" + oldEventId);
        if (oldEventId != null) {
          oldInnerAcctMap = (Map<Long, String>) reverseMap5
              .get(oldEventId);// 找到反向map
          if (oldInnerAcctMap != null && oldInnerAcctMap.size() > 0) {
            oldInnerAcctMap.remove(acctId);
          }
          if (oldInnerAcctMap != null && oldInnerAcctMap.size() == 0) {
            reverseMap5.remove(oldEventId);
          }
        }
        map5.put(acctId, c.getEventId());
        innerAcctMap.put(acctId, c.getEventId());
      }
      reverseMap5.put(c.getEventId(), innerAcctMap);
    }
  }


  /**
   * 规则六：
   * 依赖条件：如果当前任务的销售品ID在本规则的map中存在，则构成依赖，被依赖任务ID从map对应位置取得；9 存在销售品
   * 被依赖条件：如果当前任务的动作=销售品动作，如果存在依赖，则更新依赖判断任务ID=当前任务ID，否则则产生一条被依赖条件，依赖判断标识=当前任务的销售品ID，依赖判断任务ID=当前任务ID
   */
  private  void doRule6(CsipC2uEvents c, String boActionType,
      Map<String, List<Long>> map) {
    boolean isOfferIdIdExists = false;
    List<Long> offerList = null;
    Map<Long, String> innerOffer = new HashMap<Long, String>();
    Map<Long, String> oldInnerOffer = new HashMap<Long, String>();
    offerList = map.get("OFFERS");
    if (offerList != null && offerList.size() > 0) {
      for (Long offerId : offerList) {// offerId 不为空的话，则证明是销售品动作
        isOfferIdIdExists = (map6.get(offerId) == null) ? false : true;
        // 依赖关系
        if (isOfferIdIdExists) {// 如果存在，产生一条依赖关系，放入set
          logger.debug("-----do rule6 isOfferIdIdExists:"
              + isOfferIdIdExists);
          dependSet.add(map6.get(offerId));
        }
        // 被依赖关系
        // 如果当前任务的动作=销售品动作，如果存在依赖，则更新依赖判断任务ID=当前任务ID，否则则产生一条被依赖条件，依赖判断标识=当前任务的销售品ID，依赖判断任务ID=当前任务ID
        String oldEventId = map6.get(offerId);
        logger.debug("oldEventId:" + oldEventId);
        if (oldEventId != null) {
          oldInnerOffer = (Map<Long, String>) reverseMap6
              .get(oldEventId);
          if (oldInnerOffer != null && oldInnerOffer.size() > 0) {
            oldInnerOffer.remove(offerId);
          }
          if (oldInnerOffer != null && oldInnerOffer.size() == 0) {
            reverseMap6.remove(oldEventId);
          }
        }
        innerOffer.put(offerId, c.getEventId());
        map6.put(offerId, c.getEventId());
      }
      reverseMap6.put(c.getEventId(), innerOffer);
    }
  }


}
